home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
assemblr
/
library
/
sampler0
/
snoop.asm
< prev
next >
Wrap
Assembly Source File
|
1987-05-20
|
94KB
|
2,513 lines
; snoop.asm
;
; Written By Ray Smith
; Bix Name: rjsmith
; Copyright (c) 1987, Smith, Brittain & Associates. All rights reserved.
;
;
;*****************************************************************************
; Usage: snoop [/d] [/e] [/i] [/m] [/a] [/x] [/n]
;
; where d = resident and installed device drivers
; e = system equipment and configuration
; i = Invars Table
; m = Memory Control Blocks
; a = all of the above
; x = all of the above except /e
; n = do Not pause the display, allowing the output to be
; redirected to a file in a continuous stream.
;
;*****************************************************************************
;
;
.8087
cseg segment para public 'code'
org 100h ; this will be a .com file
assume cs:cseg,ds:cseg ; all seg regs point to start of PSP
main proc far
;
begin: jmp entry ; go around the data
;
;***********************************************************************
;* Explanation of bit settings in byte "config_flag"
;***********************************************************************
;
; Value 8 4 2 1 8 4 2 1
; +-----------------+-----------------+
; Bit | | |
; Number | 07 06 05 04 | 03 02 01 00 |
; | | |
; +-----------------+----------------------------------------+
; 01 | | | | | | | | 1 = PC/AT Class Machine |
; 02 | | | | | | | 1 = Enhanced BIOS Present |
; 04 | | | | | | 1 = Enhanced Keyboard Attached |
; 08 | | | | | 1 = Compaq DeskPro 386 or klone |
; 10 | | | | 1 = PC/XT Class Machine |
; 20 | | | 1 = PC Class Machine |
; 40 | | 1 = PC Convertible |
; 80 | 1 = PC/XT 089 |
; +----------------------------------------------------------+
;
;
display_flag db 0h
config_flag db 0h
equ_flag db 0h
inv_flag db 0h
drv_flag db 0h
pse_flag db 0h
mem_flag db 0h
cpu_flag db 0h
ps2_flag db 0h
sys_flag db 0h
env_flag db 0h
psp_flag db 0h
tsr_flag db 0h
mt_flag db 0h
data_flag db 0h
switchar db 2Fh ; "/" for command line switches
pathchar db 5Ch ; "\" for path name delimiter
switch_err db 0h
scan_code db 44h
loop_count dw 0h
arg_cnt dw 0h
argc db 0h
optcnt db 0h
portcnt db 0h
total_pages dw 0h
avail_pages dw 0h
firstenv db 01h
firstpsp db 01h
firstmcb db 01h
firstsys db 01h
one db 01h
linecnt db 0h
de_allocmsg db 'Deallocated$'
systype db 'DOS $'
psptype db 'PSP $'
envtype db 'ENV $'
datatype db 'DATA$'
mttype db 'Unkn$'
lastdpb db 'Chain Ends$'
notread db 'nr$' ; drive was not read
dos_vers dw 0h
emm_vers db 0h
rom_flag db 0FFh
get_key db 0h ; default BIOS Int 16h function to read a key
avail_c db 01h ; default BIOS Int 16h function to check avail char
get_sts db 02h ; default BIOS Int 16h function to check shift status
control dw 0h ; save 80x87 control word
sav_code db 0h
sav_addr dw 0h
sav_off dw 0h
invar_seg dw 0h
invar_off dw 0h
dpb_seg dw 0h
dpb_off dw 0h
sav_name db ' '
db '$'
type_drv dw 0h
devh_seg dw 0h ; segment address NUL device driver
devh_off dw 0h ; offset address NUL device driver
next_seg dw 0h ; next seg addr
next_off dw 0h ; next off addr
colon db ':'
emm_name db 'EMMXXXX0' ; Guaranteed emm device driver file name
blank db 20h
ourcopy db 0Dh,0Ah,' Copyright (c) 1987 Smith, Brittain & Associates. '
db 'All Rights Reserved.$'
mcbseg dw 0h
filename db ' $'
dataname db ' $'
db 'Written By Raymond J. Smith'
msg1 db 0Dh,0Ah,' Machine is an IBM PC/AT or AT klone $'
msg1A db 0Dh,0Ah,' Machine is an IBM PC/AT Model 339 $'
msg1B db 0Dh,0Ah,' Machine is an IBM PC/AT Model 239 $'
msg1C db 0Dh,0Ah,' Machine is an IBM PC/AT Model 099 $'
msg1D db 0Dh,0Ah,' Machine is a Compaq Dekspro 386 or compatible$'
msg1E db 0Dh,0Ah,' Machine is an IBM Personal System/2 Model 30$'
msg1F db 0Dh,0Ah,' Machine is an IBM Personal System/2 Model 50$'
msg1G db 0Dh,0Ah,' Machine is an IBM Personal System/2 Model 60$'
msg1H db 0Dh,0Ah,' Machine is an IBM Personal System/2 Model 80$'
msg2 db 0Dh,0Ah,' Enhanced BIOS is present $'
msg3 db 0Dh,0Ah,' Enhanced Keyboard is attached $'
msg4 db 0Dh,0Ah,' Machine ID byte contains code ==> $'
msg5 db 0Dh,0Ah,' No Enhanced BIOS is present $'
msg6 db 0Dh,0Ah,' No Enhanced Keyboard is attached $'
msg7 db 0Dh,0Ah,' Press any key to continue... $'
msg9 db 0Dh,0Ah,' EGA is active adapter $'
msg10 db 0Dh,0Ah,' EGA is active and is monochrome $'
msg11 db 0Dh,0Ah,' EGA is not active, a MDA or Hercules card is active $'
msg12 db 0Dh,0Ah,' EGA is not active, a CGA is active $'
msg14 db 0Dh,0Ah,' EGA has 64kb graphics memory installed $'
msg15 db 0Dh,0Ah,' EGA has 128kb graphics memory installed $'
msg16 db 0Dh,0Ah,' EGA has 192kb graphics memory installed $'
msg17 db 0Dh,0Ah,' EGA has 256kb graphics memory installed $'
msg18 db 0Dh,0Ah,' Enhanced Color Display is attached $'
msg18A db 0Dh,0Ah,' Enhanced Color Display in Color Graphics mode is attached $'
msg19 db 0Dh,0Ah,' Normal Color Display is attached $'
msg19A db 0Dh,0Ah,' CGA is active$'
msg20 db 0Dh,0Ah,' Monochrome Display is active$'
msg21 db 0Dh,0Ah,' Machine is an IBM PC/XT or XT klone $'
msg22 db 0Dh,0Ah,' Machine is an IBM PC or PC klone $'
msg23 db 0Dh,0Ah,' Machine is an IBM PC convertible $'
msg24 db 0Dh,0Ah,' Machine is a PC/XT Model 089 $'
msg25 db 0Dh,0Ah,' Machine is a PC/XT Model 286 $'
msg26 db 0Dh,0Ah,' EGA switches improperly set $'
msg27 db 0Dh,0Ah,' 8087 is installed $'
msg28 db 0Dh,0Ah,' 80287 is installed $'
msg29 db 0Dh,0Ah,' no NDP is installed$'
msg30 db ' exTEnded memory installed$',0Dh,0Ah
msg31 db ' exPAnded memory installed$'
msg31A db ' total EMS pages$'
msg31B db ' available EMS pages$'
msg31C db 0Dh,0Ah,' EMM Version: $'
msg32 db 0Dh,0Ah,' no$'
msg33 db 0Dh,0Ah,' System is operating under DOS Version $'
msg33A db 0Dh,0Ah,' Switch character currently in effect is $'
msg33B db 0Dh,0Ah,' DOS Int 21h Function 37h not responding$'
msg34 db ' is installed$'
msg35 db '3.00$'
msg36 db '3.10$'
msg37 db '3.20$'
msg37A db '3.30$'
msg37B db '3.40$'
msg38 db '2.00$'
msg39 db '2.10$'
msg40 db 'is unknown$'
msg41 db 'kb$'
msg42 db ' base memory installed$',0Dh,0Ah
msg43 db ' OR the EMM is not installed$'
msg44 db 'LPT1: $'
msg45 db 'LPT2: $'
msg46 db 'LPT3: $'
msg47 db 'COM1: $'
msg48 db 'COM2: $'
msg48A db 'COM3: $'
msg48B db 'COM4: $'
msg49 db 'No Parallel Ports active$'
msg50 db 'No Serial Ports active$'
msg98 db '2.x$'
msg99 db '3.x$'
copyrite db 'ROM BIOS Copyright ==> $'
biosdate db 'ROM BIOS dated $'
egacopy db 'EGA BIOS Copyright ==> $'
egadate db 'EGA BIOS dated $'
baddrv db 'Corrupted EMM Driver $'
badbrd db 'Malfunction in exPAnded memory hardware$'
romid db 'Adapter ROM signature found at segment $'
noroms db 'No adapter ROMs detected $'
newline db 0Dh,0Ah,'$'
indent db ' $'
rom_sig dw 0AA55h
tbuff db 255 dup('$')
char_dev db 'Char $'
blk_dev db 'Block $'
clk_dev db 'Clock $'
cmndmsg db 'COMMAND $'
sysmsg db 'System $'
freemsg db 'Free $'
mtblkmsg db '<Empty> $'
unknmsg db 'Unknown $'
envmsg db 'Process Env $'
mastenv db 'Master Env $'
tsrmsg db 'TSR $'
resdmsg db 'Resident part$'
datamsg db 'Process Data $'
thismsg db 'Transient $'
drvmsg db 'Dev Drvs, etc$'
space1 db ' $'
space2 db ' $'
space3 db ' $'
space4 db ' $'
space5 db ' $'
space6 db ' $'
space7 db ' $'
space8 db ' $'
space9 db ' $'
space10 db ' $'
space11 db ' $'
space12 db ' $'
space13 db ' $'
space14 db ' $'
scr1 db 0Dh,0Ah,' Partial Contents of DOS "Invar" Table'
db 0Dh,0Ah,' '
db 0Dh,0Ah,' Invar First 1st Dir Size of Drive/Directory DOS "Busy"'
db 0Dh,0Ah,' Table DPB Table Buffer 1 Cache Table Flag'
db 0Dh,0Ah,' Seg : Off Seg : Off Seg : Off Buffer Seg : Off Seg : Off'
db 0Dh,0Ah,' --------- --------- --------- ------- --------- --------- $'
scr1A db 0Dh,0Ah,' Contents of DPB Table By Drive'
db 0Dh,0Ah,' Dev Drvr Next DPB'
db 0Dh,0Ah,'Drv DU BPC SPC RS CF MDE FUS TCC SIF FDS Hdr Addr MD Address'
db 0Dh,0Ah,'-- -- ---- --- ---- -- ---- ---- ---- --- ---- --------- -- ---------$'
scr2 db 0Dh,0Ah,' Installed Device Drivers'
db 0Dh,0Ah,' Name or Header Address Entry Points DOS'
db 0Dh,0Ah,'Type # Units Seg : Off Strat Interpt Attrib Version'
db 0Dh,0Ah,'----------------------------------------------------------------------------$'
scr3 db 0Dh,0Ah,' Memory Allocation '
db 0Dh,0Ah,' '
db 0Dh,0Ah,'MCB Points Paras Hooked'
db 0Dh,0Ah,'Addr To Blk Alloc Type Owner Comment Cmnd Line Vectors'
db 0Dh,0Ah,'---- ---- ---- ---- -------- ----------- --------- -------------------$'
cnt dw 00h
vectcnt dw 00h
blk_beg dw 00h
blk_end dw 00h
usemsg db 0Dh,0Ah,' Usage: snoop [/d] [/e] [/i] [/m] [/a] [/n]',0Dh,0Ah
db 0Dh,0Ah
db 0Dh,0Ah,' where d = list device drivers'
db 0Dh,0Ah,' e = list equipment'
db 0Dh,0Ah,' i = list Invars Table and DPBs'
db 0Dh,0Ah,' m = list Memory Control Blocks'
db 0Dh,0Ah,' a = list all of the above'
db 0Dh,0Ah,' n = do Not pause the display'
db 0Dh,0Ah,' x = list all of the above except e'
db 0Dh,0Ah,' (for non-IBM BIOS compatible machines)$'
;
;***********************************************************************
;* Beginning of Code Seg
;***********************************************************************
entry:
call switch_char ; go see what they're using for paths
mov switch_err,al ; check for error and store for later
call chk_switch ; get our command line switches
mov ah,30h ; get dos ver num
int 21h ; go do it
xchg ah,al ; turn it around
mov dos_vers,ax ; need for NUL device driver location
cmp ax,0200h ; 2.00 or greater?
jae oz_ok
bad_oz:
jmp quit ; need 2.0 or greater
oz_ok:
mov dx,offset ourcopy ; display our copyright message
call dostty
mov dx,offset newline
call dostty
cmp equ_flag,0FFh ; switch set for equipment list?
je equip_tests ; yes
jmp invar_chk ; no - bypass equipment list
equip_tests:
clc ; clear the carry flag for error rtn
mov ah,0C0h ; get configuration parameters
int 15h ; avaialable on AT class machines only
sti ; int 15h does not reenable interrupts
jc is_old ; it's a PC
cmp ah,80h ; return value if original PC
je is_old ; 86h is returned on all PS/2 models
cmp ah,86h ; return value if not new machine
jne is_new ; 86h is returned on all PS/2 models
is_old:
jmp test_more ; it's either a PS/2 or PC PC/XT class
is_new: ; determine machine type
cmp ax,00FFh ; return value if PS/2
jne not_new_mod ;
call chk_ps2
cmp ps2_flag,0h
je not_new_mod ;
jmp at_tests
not_new_mod:
cmp byte ptr es:[bx+2],0FCh ; AT class machine ID
je chk_339
jmp test_more
chk_339:
cmp byte ptr es:[bx+3],01h ; check sub-model type byte
je is_339 ; 1 means IBM AT/339 or Compaq 386
cmp byte ptr es:[bx+3],02h ; check sub-model type byte
jne next_one
jmp xt_286 ; a 2 means it's an IBM XT/286
next_one:
cmp byte ptr es:[bx+3],0h ; check sub-model type byte
je is_239 ; 0 means it's an IBM AT/239 or 099
jmp test_more ; (note:AT/239 has rom 06/10/85)
is_339: ; mach id byte is FCh - means little
call chk_cpu ; see if 386 or 286 cpu
cmp byte ptr cs:cpu_flag,03h ; is it a 386 cpu?
je is_386 ;
is_286: ; it's a 286 cpu
or byte ptr cs:config_flag,01h ; indicate PC/AT
mov dx,offset msg1A ; AT class message
call dostty
jmp at_tests
is_386:
or byte ptr cs:config_flag,09h ; indicate PC/AT class & 386 class
mov dx,offset msg1D ; Compaq DeskPro 386 Class message
call dostty
jmp at_tests
is_239:
or byte ptr cs:config_flag,01h ; indicate PC/AT
cmp byte ptr es:[bx+4],0h ; check bios level byte
je is_099 ; 0 means it's an IBM AT/099
cmp byte ptr es:[bx+4],01 ; check bios level byte
jne test_more ; 1 means it's an IBM AT/239
mov dx,offset msg1B ; Einen Klonen Machinen message
call dostty ; if all tests fail, assume klone
jmp at_tests ; test for AT type stuff
is_099:
mov dx,offset msg1C ; original 6 mHz AT
call dostty
jmp at_tests
;***********************************************************************
;* Determine Machine Type for non_AT type machines. *
;***********************************************************************
test_more:
mov ax,0F000h ; seg address of rom bios
mov es,ax ; establish addressibility
mov ax,word ptr es:[0FFFEh] ; offset of rom bios machine id byte
call chk_mod30 ; see if PS/2 Model 30 first
cmp ps2_flag,30h ; is it a PS/2 model 30?
jne not_a_30 ; if greater, is model 50/60/80
jmp chk_mem
not_a_30:
cmp al,0FCh ; not PS/2: PC/AT? Compaq 386? XT/286?
je at_ok ;
jmp not_at ; it's not PS/2 or AT class
at_ok:
or byte ptr cs:config_flag,01h ; indicate PC/AT
mov dx,offset msg1 ;
call dostty
jmp at_tests
xt_286:
or byte ptr cs:config_flag,01h ; indicate PC/AT class machine
mov dx,offset msg25 ;
call dostty
;***********************************************************************
;* These tests are applicable to AT class machines only. *
;***********************************************************************
;
at_tests:
; test for base memory
int 12h ; BIOS int 12h returns memory size
push ax ; this is safe on an AT
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
pop dx
call dec16out
mov dx,offset msg41 ; kb
call dostty
mov dx,offset msg42 ; bytes
call dostty
;
;****************************************************************************
;* Test for presence and amount of exTEnded memory (AT class machines only) *
;****************************************************************************
mov ax,8800h
int 15h
cmp ax,0h
je noexten
push ax
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
pop dx
call dec16out ; convert binary to decimal & display
mov dx,offset msg41 ; kb
call dostty
jmp extend
noexten:
mov dx,offset msg32 ; no exTEnded memory installed
call dostty
mov dx,offset msg30
call dostty
jmp chk_emm ; go see if exPAnded memory installed
extend:
mov dx,offset msg30 ; exTEnded memory is installed
call dostty
jmp chk_emm ; go see if exPAnded memory installed
;
;***********************************************************************
;* Test for machine type if not AT class. *
;***********************************************************************
not_at:
cmp ps2_flag,30h ; is this a PS/2 Model 30?
je chk_mem ; if yes, go right to mem chk
cmp al,0FEh ; is this a PC/XT ?
jne not_xt ; set flag if it is, branch if not
or byte ptr cs:config_flag,10h ; indicate PC/XT
mov dx,offset msg21 ;
call dostty
jmp chk_mem
not_xt:
cmp al,0FFh ; is this a PC ?
jne not_pc ; set flag if it is, branch if not
or byte ptr cs:config_flag,20h ; indicate PC
mov dx,offset msg22 ;
call dostty
jmp chk_mem
not_pc:
cmp al,0F9h ; is this a PC Convertible?
jne xt_089 ; set flag if it is, branch if not
or byte ptr cs:config_flag,40h ; indicate PC Convertible
mov dx,offset msg23 ;
call dostty
jmp chk_mem
xt_089:
cmp al,0FBh ; is this a new PC/XT-089?
jne unk_id ; set flag if it is, branch if not
or byte ptr cs:config_flag,80h ; indicate PC/XT-089
mov dx,offset msg24 ;
call dostty
jmp chk_mem
unk_id:
mov dx,offset msg4 ; don't recognize this Klone
call dostty
mov sav_code,al ; display the actual machine ID byte
mov cx,1 ; count of bytes to display
lea bx,[sav_code]
call show_bytes
;
;***********************************************************************
; Test for amount of conventional memory. *
;***********************************************************************
chk_mem: ; test for main memory if not AT class
; machine
int 12h ; BIOS int 12h returns memory size
push ax ; risky: only returns switch settings
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
pop dx
call dec16out
mov dx,offset msg41 ; kb
call dostty
mov dx,offset msg42 ; bytes
call dostty
;
;***********************************************************************
;* Test for presence and amount of LIM/EMS (exPAnded) memory
;***********************************************************************
;
chk_emm:
mov ah,35h
mov al,67h
int 21h
mov di,0Ah
push cs
pop ds
mov si,offset emm_name ; guaranteed device driver name
mov cx,8 ; length of file name
cld
repz cmpsb
jz chk_ems_hardware
jmp no_emm
;***********************************************************************
;* Find out if hardware is functional using Int 67h fcn 40h
;***********************************************************************
chk_ems_hardware:
mov ah,40h ;
int 67h
cmp ah,0h ; zero return code means all ok
je emm_ok
cmp ah,80h ;
je bad_drv
bad_hard:
mov dx,offset newline ;
call dostty
mov dx,offset indent
call dostty
mov dx,offset badbrd ; bad emm hardware
call dostty
jmp chk_bios
bad_drv:
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset baddrv ; bad emm driver image
call dostty
jmp chk_bios
;
;***********************************************************************
;* Find out how many pages present/available using Int 67h fcn 03h
;***********************************************************************
emm_ok:
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov ah,42h ; get number of pages
int 67h
or ah,ah
jz no_err
; put error messages here
jmp chk_bios
no_err:
mov word ptr total_pages,dx ; dx holds total number of 16kb pages
mov word ptr avail_pages,bx ; bx holds number of available pages
call dec16out ; display it
mov dx,offset msg31A ;
call dostty
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,word ptr avail_pages
call dec16out ; display it
mov dx,offset msg31B ;
call dostty
;
;***********************************************************************
;* Find out the EMS version using Int 67h fcn 07h
;***********************************************************************
;
mov ah,46h ; get emm version
int 67h ; al = version # in BCD
mov byte ptr emm_vers,al ; Major revision in upper 4 bits
; Minor revision in lower 4 bits
mov dx,offset msg31C ;
call dostty
mov al,byte ptr emm_vers
and ax,00F0h ; isolate major ver #
mov cl,4 ; shift to low bits
shr ax,cl
add al,30h ; make it ascii
mov dl,al ; set it up for stdout
call stdout ; display major version #
mov dl,2Eh
call stdout ; display a period
mov al,byte ptr emm_vers ; get emm version
and ax,000Fh ; isolate minor version
add al,30h ; make it ascii
mov dl,al ; set it up for stdout
call stdout ; display minor version #
jmp chk_bios
no_emm:
mov dx,offset msg32 ; no exPAnded memory found...
call dostty
mov dx,offset msg31
call dostty
mov dx,offset msg43 ; ...or the emm not installed
call dostty
;
;***********************************************************************
;* display copyright and rom release date and test for enhanced BIOS *
;***********************************************************************
chk_bios:
; display copyright slug
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset copyrite ; copyright header string
call dostty
cld
push es
push ds
push ds
pop es ; destination string address in es:di
mov ax,0F000h ; source string address in ds:si
mov ds,ax ; ...location of IBM AT copyright
xor ax,ax
mov cx,10h ; count of words in copyright
test byte ptr cs:config_flag,10h ; is this an older PC/XT?
jz getcopy
mov ax,0E000h ; IBM XT copyright is higher up in rom
mov cx,0Bh ; count of words (XT is shorter)
getcopy:
mov bx,cx ;
shl bx,1 ; multiply by 2 to get offset of
mov si,ax ; terminator character in dest string
mov di,offset es:tbuff
rep movsw
pop ds
pop es
mov byte ptr tbuff+[bx],'$' ; insert terminator
mov bx, offset tbuff
scan:
cmp byte ptr[bx],'$' ; are we done?
je end_scan ; go display it
cmp byte ptr[bx],' ' ; less than a space?
jb hide_it ;
cmp byte ptr[bx],'~' ; greater than a tilde
jna bump_bx ; if not it's printable
hide_it:
mov byte ptr[bx],20h ; make nonsense characters a space
bump_bx:
inc bx ; increment the address
jmp scan ; go do it again
end_scan:
mov dx,offset tbuff ;
call dostty
push es
push ds
push ds
pop es ; destination string address in es:di
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset biosdate ; date header
call dostty
mov ax,0F000h ; source string address in ds:si
mov ds,ax
mov ax,0FFF5h ;offset of rom release date
mov si,ax
mov di,offset es:tbuff
mov cx,04h ; count of words
rep movsw
pop ds
pop es
mov byte ptr tbuff[08h],'$' ; insert string terminator
mov dx,offset tbuff
call dostty
; check for enhanced bios
mov ah,2 ; get shift status (old function)
int 16h ;
mov bl,al ; Save shift status
not al ; change al (invert all bits)
mov ah,12h ; new BIOS extended shift status
int 16h ;
cmp al,bl ; is result the same from both calls?
jne next1 ; if not, this is not enhanced BIOS
or byte ptr cs:config_flag,02h ; indicate enhanced BIOS present
mov ax,40h ; seg address of BIOS data area
mov es,ax ; establish addressibility
mov al,byte ptr es:[96h] ; offset of BIOS @KB_FLAG_3 byte
test al,10h ; is enhanced keyboard attached?
jz next1 ; set flag if it is, branch if not
or byte ptr cs:config_flag,04h ; indicate enhanced keyboard attached
test byte ptr cs:config_flag,06h ; could be new XTs with enhanced BIOS
jz next1 ; branch if not
add get_key,10h ; if new bios...
add avail_c,10h ; ...and new keyboard...
add get_sts,10h ; ...add 10h to get extended functions
next1:
test byte ptr cs:config_flag,02h ; is enhanced BIOS present?
jz old_bios ; branch if not
mov dx,offset msg2
call dostty
jmp new_bios
old_bios:
mov dx,offset msg5
call dostty
new_bios:
test byte ptr cs:config_flag,04h ; is enhanced keyboard present?
jz not_enhanced ; branch if not
mov dx,offset msg3 ;
call dostty
mov scan_code,86h ; ascii code for F12
jmp scan_rom
not_enhanced:
mov dx,offset msg6
call dostty
;***********************************************************************
;* Scan ROM for BIOS IDs...
;***********************************************************************
scan_rom:
mov dx,0C000h ; start point for rom signature scan
mov di,word ptr rom_sig ; rom signature is 55 AA hex
scan_loop:
mov es,dx
xor bx,bx ; offset zero
mov ax,es:[bx] ;
cmp ax,di ; equal to 55 AA ?
jnz next_blk ; if no, go increment block address
mov ax,es ; get segment address for display
push dx
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset romid ; ROM detected message
call dostty
call disp_hex
mov al,'h'
call stdout
mov rom_flag,0h ; indicate an adapter ROM was found
pop dx
next_blk:
add dx,80h ; point to next 2k address
chk_addr:
cmp dx,0F600h ; end of addresses where ROMs can be?
jl scan_loop ; search for more if not
no_roms:
cmp rom_flag,0h ; was an adapter ROM found?
je end_rom ; yes? bypass message
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset noroms ; no ROMs detected
call dostty
end_rom:
;
;***********************************************************************
;* Check active display and adapter
;***********************************************************************
;
chkdisp: ; check for presence of an EGA first
mov bx, 0FF10h ; see if EGA responds
mov ah, 12h
int 10h
test bh, 0FEh ; bl has mem size
jnz notega ; cl has switch settings
jmp IsEga
notega: ; see if MDA or CGA or HGC
mov ax,40h ; seg address of BIOS data area
mov es,ax ; establish addressibility
mov al,byte ptr es:[10h] ; offset of video status byte
and al,00110000b ; isolate bits 4 & 5
cmp al,30h ; is it monochrome card?
je is_mono ; assume color if not mono
mov dx,offset msg19A ; CGA is active adapter
call dostty
jmp chk_ndp
is_mono:
mov dx,offset msg20 ; MDA is active adapter
call dostty
jmp chk_ndp
IsEga:
call ega_copy ; bl and cl get clobbered
mov al,byte ptr es:[87h] ; offset of EGA BIOS data byte INFO
shl al,1
shl al,1
shl al,1
shl al,1
test al,0h ; look for EGA with color
jnz nocolor ; if not, see if mono attached
mov dx,offset msg9 ; EGA is active adapter
call dostty
mov al,byte ptr es:[88h] ; offset of EGA BIOS data byte INFO_3
shl al,1
shl al,1
shl al,1
shl al,1
test al,09h ; EGA with ECD in hi res mode
jnz nothires ; set flag if it is, branch if not
mov dx,offset msg18 ;
call dostty
jmp chkmem
nothires:
test al,01h ; EGA with ECD, EGA in CGA mode
jnz noecd ; set flag if it is, branch if not
mov dx,offset msg18A ; ECD is in CGD emulation mode
call dostty
jmp chkmem
noecd:
test al,0Eh ; EGA with Normal Color Display
jnz nocolor ; set flag if it is, branch if not
mov dx,offset msg19 ;
call dostty
jmp chkmem
nocolor:
test al,0Dh ; look for EGA with monochrome display
jnz mono2 ; set flag if it is, branch if not
mov dx,offset msg20 ;
call dostty
jmp chkmem
mono2:
test al,05h ; look for EGA with monochrome display
jnz badswitch ; set flag if it is, branch if not
mov dx,offset msg20 ;
call dostty
jmp chkmem
badswitch: ; switches must be set incorrectly
mov dx,offset msg25 ;
call dostty
;
;***********************************************************************
;* Test for amount of graphics memory on EGA
;***********************************************************************
;
chkmem:
mov ax,40h
mov es,ax
mov al,byte ptr es:[87h] ; offset of EGA BIOS data byte INFO
and al,60h ; get rid of unwanted bits
cmp al,60h ; is 256kb onboard?
jne not256 ; no - check for 192kb
mov dx,offset msg17 ;
call dostty
jmp chk_ndp
not256:
cmp al,40h ; is 192kb onboard? (is IBM EGA)
jne not192 ; no - check for 128kb
mov dx,offset msg16 ;
call dostty
jmp chk_ndp
not192:
cmp al,20h ; is 128kb onboard? (is IBM EGA)
jne not128 ; no - check for 64kb
mov dx,offset msg15 ;
call dostty
jmp chk_ndp
not128: ; *must* be 64kb memory (is IBM EGA)
mov dx,offset msg14 ;
call dostty
jmp chk_ndp
;
;***********************************************************************
;* Test for presence of 80x87. *
;***********************************************************************
;
chk_ndp:
fninit ; finit - see if 8087 installed
sub ax,ax ; fn means no wait in case no ndp
mov word ptr control,ax ; move two zeros to cntrl reg save area
fnstcw control ; get 8087 control word - no wait
mov ax,word ptr control ; put control word in ax
and ax,037Fh ; default initialization state
cmp ax,037Fh ; equal to 8087 here?
jne no_ndp ; no - go around
cmp ps2_flag,30h ; is it a PS/2 model 50 or above?
ja is_80287 ; if so it's an 80287
test byte ptr config_flag,01h ; is this an 80286 class machine ?
jz is_8087 ; if not, NDP is 8087
is_80287:
mov dx,offset msg28 ; else it's an 80287
call dostty
jmp getvers
is_8087:
mov dx,offset msg27
call dostty
jmp getvers
no_ndp:
mov dx,offset msg29
call dostty
;
;***********************************************************************
;* Display DOS Version
;***********************************************************************
;
getvers:
mov dx,offset msg33
call dostty
mov ax,dos_vers
cmp ax,0200h ; 2.00 or greater?
ja isver3
mov dx,offset msg38 ; it's 2.00
call dostty
jmp endvers
isver3:
cmp ax,0300h ; 3.00 or greater?
jae which3
mov dx,offset msg39 ; no, must be 2.10
call dostty
jmp endvers
which3:
cmp al,0Ah ; 3.10 ?
jne mustbe32
mov dx,offset msg36
call dostty
jmp endvers
mustbe32:
cmp al,14h ; 3.20 ?
jne mustbe33
mov dx,offset msg37 ; 3.20
call dostty
jmp endvers
mustbe33:
cmp al,1Eh ; 3.30 ?
jne unk_dos
mov dx,offset msg37A ; 3.30
call dostty
jmp endvers
unk_dos:
mov dx,offset msg40 ; unknown version number
call dostty
jmp quit
endvers:
;
;***********************************************************************
;* Display the active switch character
;***********************************************************************
cmp switch_err,0h ; was there a switchar error?
je fcn_37_ok
mov dx,offset msg33B
call dostty
fcn_37_ok:
mov dx,offset msg33A
call dostty
mov al,switchar ; display the *current* switchar
call stdout
;
;***********************************************************************
;* Display the active Lpt: ports
;***********************************************************************
;
chklpt:
mov ax,40h ; ROM BIOS data area segment address
mov es,ax
mov ax,word ptr es:[8h] ; offset of lpt I/O addresses
cmp ax,0h
je no_lpt1
inc portcnt
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset msg44 ; lpt1:
call dostty
call disp_hex
mov al,'h'
call stdout
no_lpt1:
mov ax,word ptr es:[0Ah]
cmp ax,0h
je no_lpt2
inc portcnt
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset msg45 ; lpt2:
call dostty
call disp_hex
mov al,'h'
call stdout
no_lpt2:
mov ax,word ptr es:[0Ch]
cmp ax,0h
je no_lpt3
inc portcnt
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset msg46 ; lpt3:
call dostty
call disp_hex
mov al,'h'
call stdout
no_lpt3:
cmp portcnt,0h
je no_prns
jmp chkcom
no_prns:
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset msg49 ; no lpt ports found
call dostty
;
;***********************************************************************
;* Display the active Com: ports
;***********************************************************************
;
chkcom:
and portcnt,0h
mov ax,word ptr es:[0h] ; offset of com I/O addresses
cmp ax,0h
je no_com1
inc portcnt
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset msg47 ; com1:
call dostty
call disp_hex
mov al,'h'
call stdout
no_com1:
mov ax,word ptr es:[02h]
cmp ax,0h
je no_com2
inc portcnt
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset msg48 ; com2:
call dostty
call disp_hex
mov al,'h'
call stdout
no_com2:
mov ax,word ptr es:[04h]
cmp ax,0h
je no_com3
inc portcnt
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset msg48A ; com3:
call dostty
call disp_hex
mov al,'h'
call stdout
no_com3:
mov ax,word ptr es:[06h]
cmp ax,0h
je no_com4
inc portcnt
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset msg48B ; com4:
call dostty
call disp_hex
mov al,'h'
call stdout
no_com4:
cmp portcnt,0h
je no_coms
jmp next_chk
no_coms:
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset msg50 ; no com ports found
call dostty
next_chk:
dec optcnt
call pause
;***********************************************************************
;* Display DOS Invar Table Contents. *
;***********************************************************************
invar_chk:
cmp inv_flag,0FFh ; switch set for invar list?
je disp_invar ; yes
jmp chk_dev_drv ; no - bypass it.
disp_invar: ; list "Invars" table contents
mov dx,offset newline
call dostty
mov dx,offset scr1
call dostty
mov dx,offset newline
call dostty
mov dx,offset space1
call dostty
mov ah,52h ; undocumented function DOS 2.x or...
int 21h ; ...greater. Returns pointer to a...
push es ; ... DOS internal structure in es:bx
push bx ; save for later
push bx ;
pop sav_off ;
mov ax,es ; get Invars seg address for display
call disp_hex ; display it.
call split ; print the colon.
mov bx,sav_off ; restore offset
mov ax,bx ; get Invars off address for display
call disp_hex
mov dx,offset space4
call dostty
mov bx,sav_off ; restore offset
mov ax,es:[bx+2] ; get DPB segment address for display
mov dpb_seg,ax
call disp_hex
call split
mov bx,sav_off ; restore offset
mov ax,es:[bx] ; get DPB offset address for display
mov dpb_off,ax
call disp_hex
mov dx,offset space4
call dostty
mov bx,sav_off ; restore offset
mov ax,es:[bx+6] ; get cache buffer seg addr
call disp_hex
call split
mov bx,sav_off ; restore offset
mov ax,es:[bx+4] ; get cache buffer offset addr
call disp_hex
mov dx,offset space6
call dostty
mov bx,sav_off ; restore offset
mov ax,es:[bx+10h] ; get cache buffer size for display
add ax,10h ; add in size of overhead bytes (16)
call disp_hex
mov dx,offset space8
call dostty
mov bx,sav_off ; restore offset
mov ax,es:[bx+18h] ; get drive/directory table seg addr
call disp_hex
call split
mov bx,sav_off ; restore offset
mov ax,es:[bx+16h] ; get drive/directory table off addr
call disp_hex
mov dx,offset space5
call dostty
mov ah,34h ; svc 34h = get DOS "Busy" flag addr
int 21h
push bx
pop sav_off
mov ax,es ; get DOS busy seg address for display
call disp_hex
call split
mov bx,sav_off ; restore offset
mov ax,bx ; get DOS busy off address for display
call disp_hex
;
;***********************************************************************
;* Display Disk Paramter Blocks.
;***********************************************************************
dpb:
mov dx,offset newline
call dostty
mov dx,offset scr1A
call dostty
mov ax,dpb_seg
mov es,ax
mov bx,dpb_off
dpb_loop:
mov dx,offset newline
call dostty
mov al,byte ptr es:[bx] ; get drive id
add al,41h ; convert to ascii letter
call stdout
call split
mov dx,offset space2
call dostty
mov al,byte ptr es:[bx+01h] ; get unit number (watch VDISKs)
; media descriptor FEh indicates vdisk?
add al,31h ; convert to ascii numeral
call stdout
mov dx,offset space2
call dostty
mov ax,word ptr es:[bx+02h] ; bytes per sector
mov cx,word ptr es:[bx+05h] ; num of bits to shift BPS to get BPC
shl ax,cl ; multiply it
call disp_hex
mov dx,offset space2 ;
call dostty
mov al,byte ptr es:[bx+04h] ; get Sectors Per Cluster minus 1
cmp al,0FEh ; this value indicates that ...
je not_read ; ... the drive was never accessed
jmp was_read
not_read:
mov dx,offset notread
call dostty
mov dx,offset space2
call dostty
jmp res_sect
was_read:
inc al ; make SPC-1 SPC
add al,30h ; make ascii char
call stdout
mov dx,offset space3
call dostty
res_sect:
mov ax,word ptr es:[bx+06h] ; Reserved Sectors
call disp_hex
mov dx,offset space2
call dostty
mov al,byte ptr es:[bx+08h] ; get Copies of FAT
add al,30h ; make ascii char
call stdout
mov dx,offset space2
call dostty
mov ax,word ptr es:[bx+09h] ; Maximum Directory Entries
call disp_hex
mov dx,offset space2
call dostty
mov ax,word ptr es:[bx+0Bh] ; First Usable Sector
call disp_hex
mov dx,offset space2
call dostty
mov ax,word ptr es:[bx+0Dh] ; Total Cluster Count plus 1
dec ax ; make it TCC
call disp_hex
mov dx,offset space3
call dostty
mov al,byte ptr es:[bx+0Fh] ; get Sectors in FAT
mov sav_code,al ; display low order byte
mov cx,1 ; count of bytes to display
push bx
lea bx,[sav_code]
call show_bytes
pop bx
mov dx,offset space2
call dostty
mov ax,word ptr es:[bx+10h] ; get First Directory Sector
call disp_hex
mov dx,offset space2
call dostty
mov ax,word ptr es:[bx+14h] ; get dev drv seg addr
call disp_hex
call split
mov ax,word ptr es:[bx+12h] ; get dev drv off addr
call disp_hex
mov dx,offset space2
call dostty
mov ax,word ptr es:[bx+16h] ; get Media Descriptor
cmp al,00h ; if zero, drive was never accessed
jne good_md
mov dx,offset notread
call dostty
mov dx,offset space2
call dostty
jmp next_link
good_md:
mov sav_code,al ; display low order byte
mov cx,1 ; count of bytes to display
push bx
lea bx,[sav_code]
call show_bytes
pop bx
mov dx,offset space2
call dostty
next_link:
mov dx,word ptr es:[bx+18h] ; get off of next dpb
cmp dx,0FFFFh ; last dpb in chain?
jne next_dpb
jmp end_dpb
next_dpb:
mov ax,word ptr es:[bx+1Ah] ; get next DPB seg addr
call disp_hex
call split
mov ax,word ptr es:[bx+18h] ; get next DPB off addr
call disp_hex
mov ax,word ptr es:[bx+1Ah] ; get seg of next dpb
mov dx,word ptr es:[bx+18h] ; get off of next dpb
mov es,ax ; establish addressibility
mov bx,dx
jmp dpb_loop
end_dpb:
mov dx,offset lastdpb
call dostty
mov dx,offset newline
call dostty
dec optcnt
call pause
pop bx
pop es
;
;***********************************************************************
;* Display Device Driver Info.
;***********************************************************************
chk_dev_drv:
cmp drv_flag,0FFh ; switch set for device driver list?
je nul_dev ; yes
jmp chk_tsr ; no - bypass driver list
nul_dev: ; list device driver section
mov ah,52h ; undocumented function DOS 2.x or...
int 21h ; ...greater. Returns pointer to a...
push es ; ... DOS internal structure in es:bx
push bx ; save for later
mov dx,offset newline
call dostty
mov dx,offset scr2
call dostty
pop bx
pop es
cmp dos_vers+1,03h ; Version dependent...
je add_34 ;
add bx,17h ; add 23 byte offset if DOS 2.x
jmp is_two
add_34:
add bx,22h ; add 34 byte offset if DOS 3.x
is_two:
mov devh_seg,es ; segment of device header chain in es
mov devh_off,bx ; offset of NUL device now in bx
mov ax,es:[bx+2] ; get seg of next driver in chain
mov next_seg,ax ; save it
mov ax,es:[bx] ; get offset of next driver in chain
mov next_off,ax ; save it
drv_loop:
cmp ax,0FFFFh ; end of chain?
jne more_drv
jmp end_drv
more_drv:
mov ax,es:[bx+2] ; get seg of next driver in chain
mov next_seg,ax ; save it
mov ax,es:[bx] ; get off of next driver in chain
mov next_off,ax ; save it
mov dx,offset newline
call dostty
mov sav_off,bx ; save offset
mov ax,es:[bx+04h] ; attribute word
mov type_drv,ax ; put it where I can get it
test ax,8000h ; what kind of device: blk or char?
jz is_block
mov dx,offset char_dev ; is character device
call dostty ; display the word "Char"
jmp is_char
is_block:
mov dx,offset blk_dev ; is block device
call dostty ; display the word "Block"
call blk_name ; format the block device name
jmp clean_up_name
is_char:
mov ax,word ptr es:[bx+0Ah] ; move name to my buffer
mov word ptr sav_name+0,ax
mov ax,word ptr es:[bx+0Ch]
mov word ptr sav_name+2,ax
mov ax,word ptr es:[bx+0Eh]
mov word ptr sav_name+4,ax
mov ax,word ptr es:[bx+10h]
mov word ptr sav_name+6,ax
mov ax,2020h ; pad name to 12 chars
mov word ptr sav_name+8,ax
mov word ptr sav_name+10,ax
mov word ptr sav_name+12,ax
mov byte ptr sav_name+13,0FFh ; the field termination character
clean_up_name:
push bx
mov bx, offset sav_name
scan2:
cmp byte ptr[bx],0FFh ; are we done?
je end_scan2 ; go display it
cmp byte ptr[bx],20h ; less than a space?
jb hide_it2
cmp byte ptr[bx],'z' ; greater than lower case z?
jna bump_bx2 ; if not it's printable
hide_it2:
mov byte ptr[bx],20h ; make nonsense characters a space
bump_bx2:
inc bx ; increment the address
jmp scan2 ; go do it again
end_scan2:
pop bx
mov dx,offset sav_name ; print dev name even if block dev
call disp_dev_drv
mov dx,offset space2
call dostty
mov ax,es ; get this driver's seg addr
call disp_hex
call split
mov bx,sav_off ; restore offset
mov ax,bx ; get this driver's off addr
call disp_hex
mov dx,offset space7 ;
call dostty
; strategy offset
mov bx,sav_off ; restore offset
mov ax,es:[bx+06h] ; get strategy offset
call disp_hex
mov dx,offset space3 ;
call dostty
; interrupt offset
mov bx,sav_off ; restore offset
mov ax,word ptr es:[bx+08h] ; get interrupt offset
call disp_hex
mov dx,offset space6 ;
call dostty
mov bx,sav_off ; restore offset
mov ax,word ptr es:[bx+04h] ; get device attribute word
call disp_hex
mov dx,offset space5 ;
call dostty
mov ax,type_drv ; check DOS version this driver
and ah,08h ; ...requires
cmp ah,08h ;
jne not_rm ; OCREM not supported - a 2.x driver
mov dx,offset msg99 ; OCREM is supported - a 3.x driver
jmp is_rm
not_rm:
mov dx,offset msg98
is_rm:
call dostty
mov bx,sav_off ; restore offset
mov es,next_seg ; get seg of next driver in chain
mov bx,next_off ; get off of next driver in chain
mov ax,bx ; set up check for end of chain
jmp drv_loop
end_drv:
dec optcnt
call pause
;***********************************************************************
;* Display Memory Control Blocks
;***********************************************************************
chk_tsr: ; list MCBs
cmp mem_flag,0FFh ; switch set for MCB list?
je mem_alloc ; yes - go do it
jmp quit ; no - quit
mem_alloc:
mov dx,offset newline
call dostty
mov dx,offset scr3 ; Memory Allocation Screen
call dostty
mov ah,52h
int 21h
mov ax,es:[bx-2] ; contains seg address of 1st MCB
mov es,ax ; establish addressibility
xor bx,bx ; offset will always be zero
mcb_loop:
and env_flag,0h ; set environment found flag "off"
and psp_flag,0h ; set PSP found flag "off"
and sys_flag,0h ; set system block found flag "off"
and tsr_flag,0h ; set TSR flag "off"
and mt_flag,0h ; set empty block found flag "off"
cmp byte ptr es:[bx],5Ah ; hex 5A is last MCB
jne mcb_2
jmp last_mcb ; process last one differently
mcb_2:
mov mcbseg,ax ; save for later
mov dx,offset newline
call dostty
xor bx,bx ; offset will always be zero
call disp_hex
mov dx, offset space2 ; will change as logic is inserted
call dostty
xor bx,bx
chk_sys:
mov ax,word ptr es:[bx+1] ; get seg addr this MCB allocates for
cmp ax,0008h ; DOS block always has 0008h here
jne chk_dealloc
or sys_flag,0FFh
and firstsys,0h
chk_dealloc: ; was this block deallocated?
push ax
mov ax,word ptr es:[bx+1] ; get seg addr this MCB allocates for
call disp_hex
mov dx, offset space3
call dostty
xor bx,bx ; offset will always be zero
pop ax
cmp ax,0000h ; is block begin zero?
jne paras ; if yes, this is empty block
or mt_flag,0FFh ; set flag (block was deallocated)
paras:
mov ax,word ptr es:[bx+3] ; get number of paragraphs allocated
call disp_hex
mov dx, offset space2
call dostty
xor bx,bx ;
search_for_env: ; does this MCB allocate for an Env?
and env_flag,0h ; clear flag
cmp byte ptr es:[bx+10h],43h ; looking for "C" in "COMSPEC="
jne no_autoexec ; yes = last MCB controls environment
cmp byte ptr es:[bx+11h],4Fh ; looking for "O" in "COMSPEC="
jne no_autoexec ; if not, maybe no autoexec.bat
jmp env_found
no_autoexec: ; if no autoexec, 1st string is PATH=
cmp byte ptr es:[bx+10h],50h ; looking for "P" in "PATH="
jne search_for_psp ; yes = last MCB controls environment
cmp byte ptr es:[bx+11h],41h ; looking for "A" in "PATH="
jne search_for_psp ; if not, no environment
env_found:
cmp firstenv,01h ; first environment?
je first_env
call get_name ; get the name of the process
or tsr_flag,0FFh
first_env:
and psp_flag,0h ; can't be both
or env_flag,0FFh ; set flag
jmp type_blk
search_for_psp: ; does this MCB allocate for a PSP?
and psp_flag,0h ; clear flag
cmp byte ptr es:[bx+10h],0CDh ; looking for an Int 20h in PSP
jne type_blk
cmp byte ptr es:[bx+11h],20h ;
jne type_blk
and env_flag,0h ; can't be both
or psp_flag,0FFh ; set flag for others
xor bx,bx
cmp firstpsp,01h
je type_blk
or tsr_flag,0FFh
type_blk:
cmp psp_flag,0FFh ; PSP?
jne type2
mov dx,offset psptype
jmp end_type
type2:
cmp env_flag,0FFh ; environment?
jne type3
mov dx,offset envtype
jmp end_type
type3:
cmp mt_flag,0FFh ; empty block?
jne type4
mov dx,offset mttype
jmp end_type
type4:
cmp sys_flag,0FFh ; system block?
jne type5
mov dx,offset systype
jmp end_type
type5:
call data_name ; save the filename if any
mov dx,offset datatype ; it's a data block
end_type:
call dostty
xor bx,bx
owner:
mov dx,offset space1
call dostty
cmp sys_flag,0FFh ; is this THE DOS block?
jne owner1
mov dx,offset sysmsg ; assume system block
jmp end_owner
owner1: ;
cmp psp_flag,0FFh ; if it's a psp and...
jne owner2 ;
cmp firstpsp,01h ; ...not the first PSP...
jne is_tsr ;
mov dx,offset cmndmsg ; it's command.com
jmp end_owner
owner2:
cmp env_flag,0FFh ; is it an environment block?
jne owner3
cmp firstenv,01h ; is it the DOS environment block?
jne is_tsr
mov dx,offset cmndmsg ; yes, it belongs to COMMAND.COM
jmp end_owner
owner3:
cmp mt_flag,0FFh ; is this block empty?
jne owner4
mov dx,offset mtblkmsg ; assume that this block is empty
jmp end_owner
owner4: ; must assume this is a data block
mov dx,offset dataname ; display last env name
jmp end_owner
is_tsr: ; this block is a TSR
mov dx,offset filename
end_owner:
call dostty ;
xor bx,bx
comments:
mov dx,offset space2
call dostty
comment1:
cmp env_flag,0FFh ; environment?
jne comment2
cmp firstenv,01h ; first environment?
je comment4
mov dx,offset envmsg ; process environment
jmp end_comment
comment2:
cmp sys_flag,0FFh ; is this a system owned block?
jne comment3
mov dx,offset drvmsg ; dev drvs, etc.
jmp end_comment
comment3:
cmp mt_flag,0FFh ; is this block empty?
jne comment5
mov dx,offset de_allocmsg ; assume that this block is empty
jmp end_comment
comment4:
mov dx,offset mastenv ; this is the DOS master environment
and firstenv,0h ; there can be only one
jmp end_comment
comment5:
cmp psp_flag,0FFh ; is this a tsr?
jne comment7
cmp firstpsp,01h ; first PSP?
je comment6
mov dx,offset tsrmsg ; TSR
jmp end_comment
comment6:
mov dx,offset resdmsg ; resident part of command.com
and firstpsp,0h ; there can be only one
jmp end_comment
comment7:
mov dx,offset datamsg ; must assume process data
jmp end_comment
end_comment:
call dostty
xor bx,bx
;***********************************************************************
;* Display the command line arguments for this TSR
;***********************************************************************
args:
call chk_args
;***********************************************************************
;* Find and display any interrupt vectors hooked by this TSR. *
;***********************************************************************
chk_vec: ; print hooked vectors here
mov dx,word ptr es:[bx+3] ; get number of paragraphs allocated
mov ax,es ; get mcb seg
inc ax ; account for length of mcb
mov blk_beg,ax ; this is where the blk begins
add ax,dx ; add the length of the blk
mov blk_end,ax ; this is where the blk ends
push es
mov ax,0h
mov es,ax
and vectcnt,0h
mov dx,vectcnt
mov cl,4
mov cnt,0h
vect_loop:
shl dx,1 ; multiply the interrupt number...
shl dx,1 ; ...by 4 to get offset of vector...
mov bx,dx ; .....in table.
mov ax,word ptr es:[bx+2] ; get the vector segment
mov dx,word ptr es:[bx] ; get the vector offset
shr dx,cl ; divide by 16 to get paragraphs
add ax,dx ; add them to get seg addr of entry
cmp ax,blk_beg ; compare the mcb seg and int seg
jnb chk_end ; int seg is greater...chk end seg
jmp not_hooked
chk_end:
cmp ax,blk_end ; compare the ending seg and int seg
jna is_hooked ; if int seg less, vector is hooked
jmp not_hooked ; ...otherwise it's not.
is_hooked:
mov ax,vectcnt ; print the interrupt number
mov sav_addr,ax ; put it where display routine wants
mov cx,1 ; count of bytes to display
lea bx,[sav_addr]
call show_bytes
mov dx, offset space1
call dostty
inc cnt
cmp cnt,05h
jbe not_hooked ; see if we have to wrap the line
and cnt,0h
mov dx,offset newline
call dostty
call chk_screen
mov dx,offset space12
call dostty ; align the wrap line
mov dx,offset space12
call dostty
mov dx,offset space12
call dostty
mov dx,offset space12
call dostty
mov dx,offset space11
call dostty
not_hooked:
mov cl,4
inc vectcnt ; increment interrupt type number
cmp vectcnt,078h ; not interested in types > 78h
ja done_vect
mov dx,vectcnt
jmp vect_loop
done_vect:
call chk_screen
pop es
end_mcb_loop:
xor bx,bx ; offset will always be zero
mov ax,mcbseg ; seg addr of MCB
mov dx,word ptr es:[bx+3] ; get number of paragraphs allocated
add ax,dx ; add paragraphs allocated to seg addr
inc ax ; +16 to account for the MCB length
mov es,ax ; this is the new seg addr
jmp mcb_loop
;***********************************************************************
;* This is the MCB for snoop.com *
;***********************************************************************
last_mcb:
or psp_flag,0FFh
mov dx,offset newline
call dostty
xor bx,bx
call disp_hex
mov dx, offset space2
call dostty
xor bx,bx
mov ax,word ptr es:[bx+1] ; get seg addr this MCB allocates for
call disp_hex
mov dx, offset space3
call dostty
xor bx,bx
mov ax,word ptr es:[bx+3] ; get number of paragraphs allocated
call disp_hex
mov dx, offset space2
call dostty
mov dx, offset psptype
call dostty
mov dx,offset space1
call dostty
mov dx,offset filename
call dostty
mov dx,offset space2
call dostty
mov dx,offset thismsg ; assume that this block is free
call dostty
call chk_args
mov dx,offset newline
call dostty
;***********************************************************************
;* End of Job. *
;***********************************************************************
quit:
mov ax,4C00h ; Return code for normal completion
int 21h ; return to DOS
main endp
;
;
;***********************************************************************
;
; Called procedures (Near)
;
;***********************************************************************
;
;***********************************************************************
;* DOS TTY Write
;***********************************************************************
dostty proc near
push ax
mov ah,09h ; ah=09h: display string at ds:dx
int 21h
pop ax
ret
dostty endp
;***********************************************************************
;* DOS Display Single Character
;***********************************************************************
dos_char proc near
push ax
mov ah,2 ; ah=02h: display char in dl
int 21h
pop ax
ret
dos_char endp
;***********************************************************************
;* Prints a colon between seg and offset addresses
;***********************************************************************
split proc near
push ax
mov al,colon
call show_ascii
pop ax
ret
split endp
;***********************************************************************
;* Prints a single space
;***********************************************************************
space proc near
push ax
mov al,blank
call show_ascii
pop ax
ret
space endp
;***********************************************************************
;* Converts Hex numbers for display.
;***********************************************************************
show_bytes proc near
push ax
push bx
push cx
sbs_loop:
mov al,[bx]
call show_byte
inc bx
loop sbs_loop
pop cx
pop bx
pop ax
ret
show_bytes endp
;***********************************************************************
;* Convert the hex character.
;***********************************************************************
show_byte proc near
pushf
push cx
push ax
mov cl,4h ;shift rt 4 bits
shr al,cl ;to isolate m.s. nybble
call test ;display hex contents
pop ax ;retrieve al
and al,0fh ;isolate l.s. nybble
call test ;display hex contents
pop cx
popf
ret
show_byte endp
;***********************************************************************
;* Determines if hex digit is a letter.
;***********************************************************************
test proc near
cmp al,9h ;is nybble letter?
ja letter ;if so convert to letter
or al,30h ;if not add '30' code
jmp display
letter:
sub al,9h ;reduce letter nybble by 9
or al,40h ;add '40' code
display:
call show_ascii
ret
test endp
;***********************************************************************
;* Displays ASCII characters.
;***********************************************************************
show_ascii proc near
push ax
push dx
mov dl,al
mov ah,02h ;ah=02: display char in dl
int 21h
pop dx
pop ax
ret
show_ascii endp
;
;*************************************************************************
;* dec16out - Routine to convert internal 16 bit binary to ASCII decimal *
;*************************************************************************
dec16out proc near
dec16out0:
push ds
push di
push dx
push cx
push ax
mov ax,cs
mov ds,ax
; a binary number is in dx
; put the digits in a temporary buffer
mov cx,0
mov di, offset cs:tbuff ; point to buffer
dec16out1:
push cx
mov ax,dx ; ax has numerator
mov dx,0
mov cx,10d ; divisor of 10
div cx
xchg ax,dx ; get quotient
add al,30h
mov [di],al ; put in buffer
inc di ; point to next byte
pop cx
inc cx ; count the digit
cmp dx,0 ; done?
jnz dec16out1
; dump the buffer out
dec16out2:
dec di ; back up through the buffer
mov al,[di]
call stdout
loop dec16out2
pop ax
pop cx
pop dx
pop di
pop ds
ret
dec16out endp
;
;***********************************************************************
;* Display device driver names so embedded "$" while display.
;***********************************************************************
disp_dev_drv proc near
push bx
push si ; save the count
xor si,si
mov bx,dx
disp_drv_loop:
cmp byte ptr ds:[bx+si],0FFh ; the field termination character
je end_drv_loop
mov al,byte ptr ds:[bx+si] ; set it up for stdout
call stdout
inc si
cmp si,0Dh ; paranoia: are we done yet?
je end_drv_loop
jmp disp_drv_loop
end_drv_loop:
pop si
pop bx
ret
disp_dev_drv endp
;
;***********************************************************************
;* Sends a character to the std ouput device.
;***********************************************************************
stdout proc near
push dx
mov dl,al ;in dl for DOS call
mov ah,2 ;send character to std output
int 21h
pop dx
ret
stdout endp
;***********************************************************************
;* Finds EGA Copyright String.
;***********************************************************************
ega_copy proc near
cmp ps2_flag,0h ; PS/2 series has onboard VGA
je not_vga ; and therefore no EGA copyright
jmp vga_exit
not_vga:
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset egacopy ; copyright header
call dostty
push es
push ds
push ds
pop es ; destination string address in es:di
mov ax,0C000h ; source string address in ds:si
mov ds,ax ; ...location of IBM EGA copyright
mov ax,05h ;
mov cx,11h ; count of words in copyright
mov bx,cx ;
shl bx,1 ; multiply by 2 then subtract 1...
dec bx ; ... to get offset of...
mov si,ax ; terminator character in dest string
mov di,offset es:tbuff
rep movsw
pop ds
pop es
mov byte ptr tbuff+[bx],'$' ; insert terminator
mov bx, offset tbuff
scan_copy:
cmp byte ptr[bx],'$' ; are we done?
je done_copy ; go display it
cmp byte ptr[bx],' ' ; less than a space?
jb mask_it ;
cmp byte ptr[bx],'~' ; greater than a tilde
jna inc_bx ; if not it's printable
mask_it:
mov byte ptr[bx],20h ; make nonsense characters a space
inc_bx:
inc bx ; increment the address
jmp scan_copy ; go do it again
done_copy:
mov dx,offset tbuff ;
call dostty
push es
push ds
push ds
pop es ; destination string address in es:di
mov dx,offset newline
call dostty
mov dx,offset indent
call dostty
mov dx,offset egadate ; date header
call dostty
mov ax,0C000h ; source string address in ds:si
mov ds,ax
mov ax,26h ; offset of EGA rom release date
mov si,ax
mov di,offset es:tbuff
mov cx,04h ; count of words
rep movsw
pop ds
pop es
mov byte ptr tbuff[07h],'$'
mov dx,offset tbuff ;
call dostty
vga_exit:
ret
ega_copy endp
;***********************************************************************
;* Division Routine.
;***********************************************************************
divide proc near
mov ax,bx
xor dx,dx
div cx
mov bx,dx
mov dl,al
cmp al,0
jz chk_flag
or display_flag,al
chk_flag:
cmp display_flag,0
ja display_it
ret
display_it:
add dl,30h
call dos_char
ret
divide endp
;***********************************************************************
; Pause the scrolling display.
;***********************************************************************
pause proc near
cmp byte ptr pse_flag,0h ; are we to pause the display?
jne no_pause ; if pause is zero we will
cmp byte ptr optcnt,0h ; last option?
jbe no_pause ; if so don't pause
push dx
mov dx,offset msg7 ;
call dostty
mov ah,get_key ; function number
int 16h ; ascii code for key pressed in ah
pop dx
no_pause:
ret ; yes - return to caller
pause endp
;***********************************************************************
;* Get a block device driver's name into a buffer for display.
;***********************************************************************
blk_name proc near
mov al,byte ptr es:[bx+0Ah] ; first byte is number of units
add al,30h ; make it ascii
mov ah,20h ; add a space
mov word ptr sav_name,ax ; store it
mov ax,es:[bx+12h] ; remainder of name...
mov word ptr sav_name+2,ax
mov ax,es:[bx+14h] ; ...if any, follows units...
mov word ptr sav_name+4,ax
mov ax,es:[bx+16h] ; ...and may include...
mov word ptr sav_name+6,ax
mov ax,es:[bx+18h] ; ....some garbage characters...
mov word ptr sav_name+8,ax
mov ax,es:[bx+1Ah] ; ...whic is unavoidable...
mov word ptr sav_name+10,ax
mov ax,es:[bx+1Ch] ; ...because I want to see the name.
mov word ptr sav_name+12,ax
mov byte ptr sav_name+13,0FFh ; the field termination character
ret
blk_name endp
;
;***********************************************************************
;* Search for Task Name in Command Line in Environment.
;***********************************************************************
get_name proc near
cmp dos_vers+1,02h ; name not available in DOS 2.x
ja vers_ok
mov arg_cnt,0h ; ignore switches
jmp quick_x ; display spaces for owner name
vers_ok:
mov dx,0000h
mov bx,10h
mov cx,532h ; env can't be longer than this
look_for:
dec cx
cmp cx,0h ; have we checked 1,330 chars?
jne not_1330 ; no, continue the search
mov arg_cnt,0h ; yes, ignore switches
jmp quick_x ; display spaces for owner name
not_1330:
inc bx ; a byte at a time.....
cmp word ptr es:[bx],dx ; ...look for back to back ascii nuls
jne look_for
add bx,2 ; found them...
mov ax,word ptr es:[bx] ; ... get count of command line args
mov arg_cnt,ax
add bx,3
cmp byte ptr es:[bx],':' ; ...looking for :\
je not_netware
mov arg_cnt,0h ; ignore switches
jmp quick_x ; display spaces for owner name
not_netware:
inc bx ; step over ":"
cmp byte ptr es:[bx],5Ch ; ...looking for "\" path delimiter
je not_novelle
cmp byte ptr es:[bx],2Fh ; ...looking for "/" path delimiter
je not_novelle ; Novelle Netware does not use either
mov arg_cnt,0h ; won't find task name so ignore
jmp quick_x ; display spaces for owner name
not_novelle:
inc bx ; step over the "\" or "/"
mov di,offset filename
mov si,bx ; si is offset of beginning of name
xor cx,cx
mov_name:
cmp byte ptr es:[si],5Ch ; looking for embedded '\' in path
je restart_scan
cmp byte ptr es:[si],2Fh ; looking for embedded '/' in path
jne no_path
restart_scan:
mov di,offset filename ; reset dest offset to beginning
inc si ; bump si past '\' or '/'
xor cx,cx
jmp mov_name ; go back and start again
no_path:
cmp byte ptr es:[si],2Eh ; looking for '.' to exclude extension
je end_name
cmp cx,8h ; filename is 8 chars long max
je fini
mov al,byte ptr es:[si]
mov byte ptr ds:[di],al
inc si
inc di
inc cx
jmp mov_name
end_name:
cmp cx,8h ; filename is 8 chars long
jnb fini
mov byte ptr ds:[di],20h
inc di
inc cx
jmp end_name
fini:
mov byte ptr ds:[di],'$'
quick_x:
xor bx,bx ; offset will always be zero
ret
get_name endp
;***********************************************************************
;* Save the filename for data blocks
;***********************************************************************
;
data_name proc near
cmp byte ptr filename,20h ; will be a space first time around
jne not_first
call get_owner ; find the owning task name
not_first:
cmp data_flag,0FFh ; if set, name is already in place
je data_exit ; exit if it is
push es ; save MCB seg addr
push ds ; establish addressibility
pop es ; destination string address in es:di
mov ax,offset filename ; offset of filename
mov si,ax ; set up source index
mov di,offset es:dataname ; set up destination index
mov cx,04h ; count of words (8 bytes)
rep movsw ; do the move
mov byte ptr dataname[08h],'$' ; string terminator for DOS
or data_flag,0FFh ; set it for next time
pop es ; restore MCB seg addr
data_exit:
ret
data_name endp
;
;***********************************************************************
;* Get name of task that owns this data block.
;***********************************************************************
get_owner proc near
push es
push bx
xor bx,bx
mov ax,word ptr es:[bx+1] ; get seg addr of blk this MCB controls
mov es,ax ; es now points to PSP of owner
mov ax,word ptr es:[bx+2Ch] ; get seg addr of environment
mov es,ax ; es now points to Env of owner
call get_name ; call the normal get name routine
pop bx
pop es
ret
get_owner endp
;
;***********************************************************************
;* Display Hex Numbers.
;***********************************************************************
disp_hex proc near
push bx
xchg ah,al ; get it turned around
mov sav_addr,ax ;
mov cx,2 ; count of bytes to display
lea bx,[sav_addr]
call show_bytes
pop bx
ret
disp_hex endp
;
;***********************************************************************
;* Check for command line switches in the TSR's PSP. *
;***********************************************************************
chk_args proc near
push bx
cmp psp_flag,0FFh ; is this a PSP?
jne no_args
cmp arg_cnt,0h ; any command line switches?
je no_args
mov bx,90h ; offset of count (including MCB)
mov ax,es:[bx] ; PSP arg cnt
cmp ax,0h ; any args?
je end_args
inc bx ; point to tail
arg_loop:
cmp byte ptr es:[bx],0Dh ; CR ends tail
je end_args
mov al,es:[bx]
call stdout
inc bx ; bump offset
cmp bx,9Bh ; only room for 9 characters
jb arg_loop
end_args:
sub bx,91h ; get number of spaces to print
cmp bx,0h
jbe no_args ; if negative, no args
mov cx,0Ch
sub cx,bx
fill_loop:
mov al,20h
call stdout
loop fill_loop
jmp exit_args
no_args:
mov dx,offset space12 ; change # of spaces for args print
call dostty ;
exit_args:
pop bx
ret
chk_args endp
;***********************************************************************
;* See if 80286 or 80386 CPU using Intel approved method
;***********************************************************************
chk_cpu proc near
push ax
mov cpu_flag,0h ; clear it
pushf ; save original flags
pushf ; make extra copy of flags register..
pop ax ; bits 12-14 can be set on a 386 only
or ax,0111000000000000b ; turn on bits 12-14
push ax ;
popf ; pop this value back into flags reg
pushf ;
pop ax ; look at results
and ax,0111000000000000b ; see if bits 12-14 are set
jnz is_32_bit ; if they're set, it's a 386 cpu
is_16_bit:
popf ; restore flags
or byte ptr cs:cpu_flag,02h ; indicate 286 cpu
jmp cpu_exit
is_32_bit:
popf ; restore flags
or byte ptr cs:cpu_flag,03h ; indicate 386 cpu
jmp cpu_exit
cpu_exit:
pop ax
ret
chk_cpu endp
;
;***********************************************************************
;* Check to see if this is an IBM Personal System/2 Machine *
;***********************************************************************
; Model Id Byte values and meanings:
;
; IBM Personal System/2 Model 30
; at address F000:FFFE FA
;
; IBM Personal System/2 Model 50
; at address E000:7AF9 FC 04 <====Rom Revision Level 4.
;
; IBM Personal System/2 Model 60
; at address E000:7B03 FC 05 <====Rom Revision Level 5.
;
; IBM Personal System/2 Model 80
; at address E000:xxxx F8 00 F8 is an educated guess
;
chk_ps2 proc near
and ps2_flag,0h
cmp word ptr es:[bx+2],04FCh
je model_50
cmp word ptr es:[bx+2],05FCh
je model_60
cmp byte ptr es:[bx+2],0F8h
je need_386
jmp unkn_model
need_386:
call chk_cpu
cmp byte ptr cs:cpu_flag,03h ; is it a 386 cpu?
je model_80
jmp unkn_model ; it's an 80286, 8088, or 8086
model_50:
or ps2_flag,50h
mov dx,offset msg1F
call dostty
jmp end_ps2
model_60:
or ps2_flag,60h
mov dx,offset msg1G
call dostty
jmp end_ps2
model_80:
or ps2_flag,80h
mov dx,offset msg1H
call dostty
jmp end_ps2
unkn_model: ; probably a PC Convertible
end_ps2:
ret
chk_ps2 endp
;
;***********************************************************************
;* chk_mod30 - Check if this is a PS/2 Model 30.
;***********************************************************************
chk_mod30 proc near
cmp al,0FAh ; PS/2 Model 30?
je model_30
jmp end_30
model_30:
or ps2_flag,30h
mov dx,offset msg1E
call dostty
end_30:
ret
chk_mod30 endp
;
;***********************************************************************
;* chk_switch - Check command line switches for options requested. * *
;***********************************************************************
chk_switch proc near
mov cl,ds:[0080h] ; command line arg count in PSP
cmp cl,0h ; any args?
ja swt_set
jmp end_swt
swt_set:
mov bx,80h ; offset-1 of command tail in PSP
swt_char:
inc bx
cmp byte ptr ds:[bx],0Dh ; CR ends command tail
jne more_swt
jmp end_swt
more_swt:
cmp byte ptr ds:[bx],'/'
je fnd_swt
cmp byte ptr ds:[bx],'\'
je fnd_swt
cmp byte ptr ds:[bx],' '
je fnd_swt
cmp byte ptr ds:[bx],'-'
je fnd_swt
jmp swt_char
fnd_swt:
inc bx
or byte ptr ds:[bx],20h
cmp byte ptr ds:[bx],'n'
jne chk_equ
or pse_flag,0FFh
and byte ptr one,0h ; value to add to the line counter
jmp swt_char
chk_equ:
cmp byte ptr ds:[bx],'e'
jne chk_inv
or equ_flag,0FFh
inc optcnt
jmp swt_char
chk_inv:
cmp byte ptr ds:[bx],'i'
jne chk_drv
or inv_flag,0FFh
inc optcnt
jmp swt_char
chk_drv:
cmp byte ptr ds:[bx],'d'
jne chk_mcb
or drv_flag,0FFh
inc optcnt
jmp swt_char
chk_mcb:
cmp byte ptr ds:[bx],'m'
jne all_chk
or mem_flag,0FFh
inc optcnt
jmp swt_char
all_chk:
cmp byte ptr ds:[bx],'a'
jne klone_chk
or equ_flag,0FFh
or inv_flag,0FFh
or drv_flag,0FFh
or mem_flag,0FFh
or argc,0FFh
jmp swt_char
klone_chk: ; option for MS-DOS boxes
cmp byte ptr ds:[bx],'x' ; which are not IBM ROM...
jne last_chk
and equ_flag,0h ; ... BIOS compatible.
or inv_flag,0FFh
or drv_flag,0FFh
or mem_flag,0FFh
or argc,0FFh
jmp swt_char
last_chk:
dec bx
jmp swt_char
end_swt:
cmp argc,0FFh
jne not_all
mov optcnt,4
not_all:
cmp optcnt,1 ; must specify one switch at least
jnb lv_swt
mov dx,offset usemsg
call dostty
mov ax,4C01h ; Return code for abnormal completion
int 21h ; return to DOS
lv_swt:
ret
chk_switch endp
;
;***********************************************************************
;* Check the switch char for path names - is it "/" or "\"?
;***********************************************************************
switch_char proc near
mov ax,3700h ; request switchar be returned in dl
int 21h
cmp dl,5CH ; are they using "\" for switches?
jne not_unix_lover ; no, "/" for switches, "\" for paths
cmp dl,2FH ; are they using "/" for switches?
jne func_not_working ; if no, the function is not working
mov switchar,5Ch ; change it around for unix lovers
mov pathchar,2Fh ; least they be troubled... :-)
jmp func_works
not_unix_lover:
cmp dl,2FH ; are they using "/" for switches?
je func_works ; the undocumented function works
func_not_working:
mov al,0FFh ; if no, the function is not working
; leave defaults in place, signal err
func_works:
ret
switch_char endp
;
;***********************************************************************
;* Check to see if screen is full during MCB display.
;***********************************************************************
chk_screen proc near
push ax
push dx
xor ax,ax
mov al,byte ptr linecnt
add al,one ; will be 0 if pause, 1 if not
cmp al,14h ; 20 lines per screen
jb not_full
mov dx,offset newline
call dostty
mov dx,offset msg7 ; press any key message
call dostty
mov ah,get_key ; function number (0h or 10h)
int 16h ; ascii code for key pressed in ah
xor al,al
not_full:
mov byte ptr linecnt,al ; store the updated counter
pop dx
pop ax
ret
chk_screen endp
;
cseg ends
end begin
;*****************************************************************************
;* End Of Source Code.
;*****************************************************************************